#ifndef __WINDOWHERO_UV_H__
#define __WINDOWHERO_UV_H__
#define _GNU_SOURCE
#include "errno2.h"
#include "mygetaddrinfo/mygetaddrinfo.h"
#include "list/list.h"
#include "log/log.h"
#include <arpa/inet.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>

#define SETNODELAY(fd, enable)  do { int _enable = enable; int _ret = setsockopt(fd, SOL_TCP,TCP_NODELAY, (void*)&_enable, sizeof(_enable)); if (_ret) LOGDIE("ddddddddddddddddddd[fd %d]\n", fd); } while(0)
#define SETNONBLOCK(fd) do { int _ret = fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); if (_ret == -1) LOGDIE("ddddddddddddddddd\n"); } while(0);
#define UV_EPOLL_ADD(h, fd, flag, p) do { struct epoll_event _ev; _ev.events = flag; _ev.data.ptr = p; if (epoll_ctl(h, EPOLL_CTL_ADD, fd, &_ev)) LOGDIE("epoll add fd %d error[%m]\n", fd); } while(0)
#define UV_TYPE_ASYNC 1
#define UV_TYPE_TCP 3
#define UV_TYPE_TIMER 2
#define UV_TYPE_IDLE 5
#define UV_TYPE_UDP 4
#define uv_strerror uv_err_name
#define UV_GETADDRINFO_BINGFA_MAX 64

#define ADD_UV_TCP_TO_READ_UV_TCP_TASKLIST(uv_tcp, head) do { \
    if (is_in_list(&uv_tcp->read_node) == 0 && uv_tcp->is_read_stop == 0 && uv_tcp->is_finish_handshake && uv_tcp->is_close_called == 0) { \
        if (head) list_add_head(&uv_tcp->read_node, &uv_tcp->loop->read_uv_tcp_tasklist); else { \
            if (uv_tcp->read_times <= 2) { \
                list_add_head(&uv_tcp->read_node, &uv_tcp->loop->read_uv_tcp_tasklist); \
            } else { \
                list_add_tail(&uv_tcp->read_node, &uv_tcp->loop->read_uv_tcp_tasklist); \
            } \
        } \
    } \
} while(0)
#define ADD_UV_TCP_TO_WRITE_UV_TCP_TASKLIST(uv_tcp) do { \
    if (is_in_list(&uv_tcp->write_node) == 0 && list_empty(&uv_tcp->write_req_list) == 0 && uv_tcp->is_finish_handshake && uv_tcp->is_close_called == 0) { \
        if (uv_tcp->write_times <= 2) { \
            list_add_head(&uv_tcp->write_node, &uv_tcp->loop->write_uv_tcp_tasklist); \
        } else { \
            list_add_tail(&uv_tcp->write_node, &uv_tcp->loop->write_uv_tcp_tasklist); \
        } \
        uv_tcp->write_times++; \
    } \
} while(0)
#define ADD_UV_UDP_TO_READ_UV_UDP_TASKLIST(uv_udp) do { \
    if (is_in_list(&uv_udp->read_node) == 0 && uv_udp->is_read_stop == 0 && uv_udp->is_close_called == 0) { \
        if (uv_udp->read_times <= 2) { \
            list_add_head(&uv_udp->read_node, &uv_udp->loop->read_uv_udp_tasklist); \
        } else { \
            list_add_tail(&uv_udp->read_node, &uv_udp->loop->read_uv_udp_tasklist); \
        } \
    } \
} while(0)
#define ADD_UV_UDP_TO_WRITE_UV_UDP_TASKLIST(uv_udp) do { \
    if (is_in_list(&uv_udp->write_node) == 0 && list_empty(&uv_udp->write_req_list) == 0 && uv_udp->is_close_called == 0) { \
        if (uv_udp->write_times <= 2) { \
            list_add_head(&uv_udp->write_node, &uv_udp->loop->write_uv_udp_tasklist); \
        } else { \
            list_add_tail(&uv_udp->write_node, &uv_udp->loop->write_uv_udp_tasklist); \
        } \
        uv_udp->write_times++; \
    } \
} while(0)

static inline const char *_uv_type_to_name(int type)
{
    switch (type) {
        case UV_TYPE_ASYNC: return "UV_ASYNC";
        case UV_TYPE_TCP:   return "UV_TCP";
        case UV_TYPE_UDP:   return "UV_UDP";
        case UV_TYPE_TIMER: return "UV_TIMER";
    }
    return "UNKNOWN_TYPE";
}

typedef enum {
  UV_RUN_DEFAULT = 0,
  UV_RUN_ONCE,
  UV_RUN_NOWAIT
} uv_run_mode;

struct uv_loop;

#define UV_HANDLE_FIELDS        \
    int type; /*must be first*/ \
    struct list_head close_node; \
    int is_close_called; \
    uv_close_cb uv_close_cb; \
    struct uv_loop *loop; \
    struct list_head node_for_epoll_out; int is_in_epoll_out_list; \
    uint32_t events; \
    void *data; \

struct uv_handle;
typedef void (*uv_close_cb)(struct uv_handle* handle);
typedef struct uv_handle {
    UV_HANDLE_FIELDS
} uv_handle_t;

typedef struct {
    UV_HANDLE_FIELDS
} uv_stream_t;
typedef void (*uv_connection_cb)(uv_stream_t* server, int status);
struct uv_loop;
struct uv_write;

typedef void (*uv_write_cb)(struct uv_write* req, int status);
typedef struct { char *base; size_t len; } uv_buf_t;

typedef struct uv_write {
    struct list_head node;
    int writed_len;
    uv_write_cb uv_write_cb;
    const uv_buf_t *buf;
    int buf_count;
} uv_write_t;

struct uv_connect;
typedef void (*uv_alloc_cb)(uv_handle_t* handle, size_t suggested_size, uv_buf_t* buf);
typedef void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf);

struct uv_shutdown_req;
typedef void (*uv_shutdown_cb)(struct uv_shutdown_req* req, int status);
typedef struct uv_shutdown_req {
    uv_shutdown_cb uv_shutdown_cb;
} uv_shutdown_t;

typedef struct uv_tcp {
    UV_HANDLE_FIELDS
    int fd;
    int accepted_fd;
    int is_connecting;
    int is_finish_handshake;
    int is_read_stop;
    int is_remote_gone;
    int epoll_say_readable;
    uint32_t read_times;
    uint32_t write_times;
    struct list_head read_node;
    struct list_head write_node;
    struct list_head write_req_list;
    struct uv_connect* uv_connect;
    uv_alloc_cb uv_alloc_cb;
    uv_buf_t read_buf;
    uv_connection_cb uv_listen_cb;
    uv_read_cb uv_read_cb;
    uv_shutdown_t *uv_shutdown_req;
} uv_tcp_t;

struct uv_udp;
typedef void (*uv_udp_recv_cb)(struct uv_udp* handle, ssize_t nread, const uv_buf_t* buf, const struct sockaddr* addr, unsigned flags);
typedef struct uv_udp {
    UV_HANDLE_FIELDS
    int fd;
    int is_read_stop;
    uint32_t read_times;
    uint32_t write_times;
    struct list_head read_node;
    struct list_head write_node;
    struct list_head write_req_list;
    uv_alloc_cb uv_alloc_cb;
    uv_buf_t read_buf;
    uv_udp_recv_cb uv_udp_recv_cb;
} uv_udp_t;
typedef void (*uv_connect_cb)(struct uv_connect* req, int status);
typedef struct uv_connect {
    uv_connect_cb uv_connect_cb;
} uv_connect_t;

struct uv_getaddrinfo;
typedef void (*uv_getaddrinfo_cb)(struct uv_getaddrinfo* req, int status, struct addrinfo* res);
typedef struct uv_getaddrinfo {
    uv_getaddrinfo_cb cb;
    struct list_head node;
    char* hostname;
    char* service;
    struct addrinfo hints;
    struct addrinfo *addrinfo;
    int retcode;
} uv_getaddrinfo_t;

typedef struct {} uv_getnameinfo_t;
struct uv_async;
typedef void (*uv_async_cb)(struct uv_async* handle);
typedef struct uv_async {
    UV_HANDLE_FIELDS
    int pipe_fd[2];
    uv_async_cb cb;
} uv_async_t;

struct uv_timer;
typedef void (*uv_timer_cb)(struct uv_timer* handle);
typedef struct uv_timer {
    UV_HANDLE_FIELDS
    struct timespec timeout;
    uint64_t interval; //haomiao
    struct list_head node;
    uv_timer_cb cb;
} uv_timer_t;

struct uv_idle;
typedef void (*uv_idle_cb)(struct uv_idle* handle);
typedef struct uv_idle {
    UV_HANDLE_FIELDS
    struct list_head node;
    uv_idle_cb cb;
} uv_idle_t;

struct _uv_timeout {
    UV_HANDLE_FIELDS //only use its node_for_epoll_out and is_in_epoll_out_list
    int pipes[2];
};

struct _uv_getaddrinfo_result {
    UV_HANDLE_FIELDS //only use its node_for_epoll_out and is_in_epoll_out_list
    int pipes[2];
};

typedef struct uv_loop {
    int epoll_fd;
    pthread_t timeout_pid;
    pthread_cond_t getaddrinfo_cond;
    pthread_mutex_t getaddrinfo_lock;
    pthread_mutex_t getaddrinfo_resultlist_lock;
    struct list_head getaddrinfo_tasklist; uint32_t getaddrinfo_tasklist_len, getaddrinfo_tasklist_len_max, getaddrinfo_task_total;
    uint32_t getaddrinfo_thread_count;
    uint32_t getaddrinfo_thread_busy;
    int closed;
    uint32_t getaddrinfo_thread_count_max;
    uint32_t getaddrinfo_thread_create_count;
    struct list_head getaddrinfo_resultlist;
    struct list_head write_uv_tcp_tasklist;
    struct list_head read_uv_tcp_tasklist;
    struct list_head close_tasklist;
    struct list_head read_uv_udp_tasklist;
    struct list_head write_uv_udp_tasklist;
    struct list_head timer_list;
    struct list_head idle_list;
    struct _uv_timeout uv_timeout;
    struct _uv_getaddrinfo_result uv_getaddrinfo_result;
    int mode;
    struct list_head child_list; uint32_t child_count; pthread_mutex_t child_lock; struct list_head node;
    struct uv_loop *parent;
#define IS_INITED_TAG 0x3846ef22
    uint32_t is_inited;
} uv_loop_t;

struct uv_udp_send;
typedef void (*uv_udp_send_cb)(struct uv_udp_send* req, int status);
typedef struct uv_udp_send {
    struct list_head node;
    const uv_buf_t *buf; int buf_count;
    uv_udp_send_cb uv_udp_send_cb;
    struct sockaddr addr;
    int is_addr_valid;
} uv_udp_send_t;
typedef void (*uv_getnameinfo_cb)(uv_getnameinfo_t* req, int status, const char* hostname, const char* service);

static inline int uv_async_init(uv_loop_t* uv_loop, uv_async_t* async, uv_async_cb cb)
{
    memset(async, 0, sizeof(*async));
    async->type = UV_TYPE_ASYNC;
    async->cb = cb;
    int ret = pipe2(async->pipe_fd, O_NONBLOCK); if (ret) LOGDIE("ddddddddddddddddddddd\n");
    UV_EPOLL_ADD(uv_loop->epoll_fd, async->pipe_fd[0], EPOLLET | EPOLLIN, async);
    return 0;
}

static inline int uv_async_send(uv_async_t* async)
{
loop:
    if (write(async->pipe_fd[1], "1", 1) != 1) {
        if (0) {
        } else if (errno == EAGAIN) {
        } else if (errno == EINTR) { goto loop;
        } else { LOGDIE("dddddddddd\n");
        }
    }
    return 0;
}

const char *uv_err_name(int err)
{
    switch (err) {
        case UV_E2BIG: return "argument list too long";                            
        case UV_EACCES: return "permission denied";                                 
        case UV_EADDRINUSE: return "address already in use";                        
        case UV_EADDRNOTAVAIL: return "address not available";                      
        case UV_EAFNOSUPPORT: return "address family not supported";                
        case UV_EAGAIN: return "resource temporarily unavailable";                  
        case UV_EAI_ADDRFAMILY: return "address family not supported";              
        case UV_EAI_AGAIN: return "temporary failure";                              
        case UV_EAI_BADFLAGS: return "bad ai_flags value";                          
        case UV_EAI_BADHINTS: return "invalid value for hints";                     
        case UV_EAI_CANCELED: return "request canceled";                            
        case UV_EAI_FAIL: return "permanent failure";                               
        case UV_EAI_FAMILY: return "ai_family not supported";                       
        case UV_EAI_MEMORY: return "out of memory";                                 
        case UV_EAI_NODATA: return "no address";                                    
        case UV_EAI_NONAME: return "unknown node or service";                       
        case UV_EAI_OVERFLOW: return "argument buffer overflow";                    
        case UV_EAI_PROTOCOL: return "resolved protocol is unknown";                
        case UV_EAI_SERVICE: return "service not available for socket type";        
        case UV_EAI_SOCKTYPE: return "socket type not supported";                   
        case UV_EALREADY: return "connection already in progress";                  
        case UV_EBADF: return "bad file descriptor";                                
        case UV_EBUSY: return "resource busy or locked";                            
        case UV_ECANCELED: return "operation canceled";                             
        case UV_ECHARSET: return "invalid Unicode character";                       
        case UV_ECONNABORTED: return "software caused connection abort";            
        case UV_ECONNREFUSED: return "connection refused";                          
        case UV_ECONNRESET: return "connection reset by peer";                      
        case UV_EDESTADDRREQ: return "destination address required";                
        case UV_EEXIST: return "file already exists";                               
        case UV_EFAULT: return "bad address in system call argument";               
        case UV_EFBIG: return "file too large";                                     
        case UV_EHOSTUNREACH: return "host is unreachable";                         
        case UV_EINTR: return "interrupted system call";                            
        case UV_EINVAL: return "invalid argument";                                  
        case UV_EIO: return "i/o error";                                            
        case UV_EISCONN: return "socket is already connected";                      
        case UV_EISDIR: return "illegal operation on a directory";                  
        case UV_ELOOP: return "too many symbolic links encountered";                
        case UV_EMFILE: return "too many open files";                               
        case UV_EMSGSIZE: return "message too long";                                
        case UV_ENAMETOOLONG: return "name too long";                               
        case UV_ENETDOWN: return "network is down";                                 
        case UV_ENETUNREACH: return "network is unreachable";                       
        case UV_ENFILE: return "file table overflow";                               
        case UV_ENOBUFS: return "no buffer space available";                        
        case UV_ENODEV: return "no such device";                                    
        case UV_ENOENT: return "no such file or directory";                         
        case UV_ENOMEM: return "not enough memory";                                 
        case UV_ENONET: return "machine is not on the network";                     
        case UV_ENOPROTOOPT: return "protocol not available";                       
        case UV_ENOSPC: return "no space left on device";                           
        case UV_ENOSYS: return "function not implemented";                          
        case UV_ENOTCONN: return "socket is not connected";                         
        case UV_ENOTDIR: return "not a directory";                                  
        case UV_ENOTEMPTY: return "directory not empty";                            
        case UV_ENOTSOCK: return "socket operation on non-socket";                  
        case UV_ENOTSUP: return "operation not supported on socket";                
        case UV_EOVERFLOW: return "value too large for defined data type";          
        case UV_EPERM: return "operation not permitted";                            
        case UV_EPIPE: return "broken pipe";                                        
        case UV_EPROTO: return "protocol error";                                    
        case UV_EPROTONOSUPPORT: return "protocol not supported";                   
        case UV_EPROTOTYPE: return "protocol wrong type for socket";                
        case UV_ERANGE: return "result too large";                                  
        case UV_EROFS: return "read-only file system";                              
        case UV_ESHUTDOWN: return "cannot send after transport endpoint shutdown";  
        case UV_ESPIPE: return "invalid seek";                                      
        case UV_ESRCH: return "no such process";                                    
        case UV_ETIMEDOUT: return "connection timed out";                           
        case UV_ETXTBSY: return "text file is busy";                                
        case UV_EXDEV: return "cross-device link not permitted";                    
        case UV_UNKNOWN: return "unknown error";                                    
        case UV_EOF: return "end of file";                                          
        case UV_ENXIO: return "no such device or address";                          
        case UV_EMLINK: return "too many links";                                    
        case UV_EHOSTDOWN: return "host is down";                                   
        case UV_EREMOTEIO: return "remote I/O error";                               
        case UV_ENOTTY: return "inappropriate ioctl for device";                    
        case UV_EFTYPE: return "inappropriate file type or format";                 
        case UV_EILSEQ: return "illegal byte sequence";                             
        case UV_ESOCKTNOSUPPORT: return "socket type not supported";                
        case 0: return "0";
        default: return "unknow error";
    }
}

#define _uv_tcp_set_fd(uv_loop, uv_tcp, __fd, flag) do { \
    uv_loop_t* _uv_loop = uv_loop; uv_tcp_t* _uv_tcp = uv_tcp; int _fd = __fd; int _flag = flag; \
    SETNONBLOCK(_fd); \
    int enable = 1; SETNODELAY(_fd, enable); \
    if (_uv_tcp->fd >= 0) LOGDIE("bug, fix me 12323\n"); \
    _uv_tcp->fd = _fd; UV_EPOLL_ADD(_uv_loop->epoll_fd, _fd, _flag, _uv_tcp); \
} while(0)

#define _uv_udp_set_fd(uv_loop, uv_udp, __fd, flag) do { \
    uv_loop_t* _uv_loop = uv_loop; uv_udp_t* _uv_udp = uv_udp; int _fd = __fd; int _flag = flag; \
    if (_uv_udp->fd >= 0) LOGDIE("bug, fix me 12324\n"); \
    _uv_udp->fd = _fd; UV_EPOLL_ADD(_uv_loop->epoll_fd, _fd, _flag, _uv_udp); \
} while(0)

//static inline int uv_accept(uv_stream_t* server, uv_stream_t* client)
#define uv_accept(server, client) ({ \
    int _ret = UV_UNKNOWN; \
    if ((server)->type == UV_TYPE_TCP) { \
        uv_tcp_t *listener = (uv_tcp_t *)server; \
        uv_tcp_t *uv_tcp   = (uv_tcp_t *)client; \
        if (listener->accepted_fd >= 0) { \
        int _new_fd = listener->accepted_fd; listener->accepted_fd = -1; ADD_UV_TCP_TO_READ_UV_TCP_TASKLIST(listener, 0); \
        _uv_tcp_set_fd(listener->loop, uv_tcp, _new_fd, EPOLLET | EPOLLIN | EPOLLOUT); \
        uv_tcp->is_finish_handshake = 1; \
        ADD_UV_TCP_TO_WRITE_UV_TCP_TASKLIST(uv_tcp); \
        _ret = 0; \
        } else { \
        _ret = UV_EAGAIN; \
        } \
    } else { \
        LOGDIE("dddddddddddddddddddd\n"); \
    } \
    _ret; \
})

#define uv_listen(stream, backlog, cb) ({ \
    uv_tcp_t *_uv_tcp = (uv_tcp_t *)stream; LOGMSG("setting fd %d in listen mode\n", _uv_tcp->fd); \
    int _ret = listen(_uv_tcp->fd, backlog); if (_ret) LOGDIE("dddddddddd\n"); \
    _uv_tcp->uv_listen_cb = cb; \
    0; })

void _read_uv_tcp(uv_tcp_t *uv_tcp)
{
    if (is_in_list(&uv_tcp->read_node)) list_del(&uv_tcp->read_node);
    if (uv_tcp->is_close_called) {
        if (uv_tcp->read_buf.base && uv_tcp->read_buf.len > 0) {
            uv_buf_t uv_buf = uv_tcp->read_buf; uv_tcp->read_buf.base = NULL; uv_tcp->read_buf.len = 0;
            uv_tcp->uv_read_cb((uv_stream_t *)uv_tcp, UV_ECANCELED, &uv_buf);
        }
        return;
    }
    if (uv_tcp->is_read_stop) { LOGMSG("fd %d, is_read_stop is true\n", uv_tcp->fd); return; }
    if (uv_tcp->uv_listen_cb) {
        int need_add_uv_tcp_to_read_task_list = 1;
        if (uv_tcp->accepted_fd < 0) {
            int new_fd = accept(uv_tcp->fd, NULL, NULL);
            if (new_fd >= 0) { uv_tcp->accepted_fd = new_fd; } else if (errno == EAGAIN) { need_add_uv_tcp_to_read_task_list = 0; } else { LOGFEW("fail to call accpet[%m]\n"); }
        }
        if (need_add_uv_tcp_to_read_task_list) ADD_UV_TCP_TO_READ_UV_TCP_TASKLIST(uv_tcp, 0);
        if (uv_tcp->accepted_fd >= 0) uv_tcp->uv_listen_cb((uv_stream_t *)uv_tcp, 0);
        return;
    }
    if (uv_tcp->is_finish_handshake == 0) return;
    if (uv_tcp->is_remote_gone) return;
    if (uv_tcp->read_buf.len <= 0 || uv_tcp->read_buf.base == NULL) { uv_tcp->uv_alloc_cb((uv_handle_t *)uv_tcp, 32000, &uv_tcp->read_buf); }
    if (uv_tcp->read_buf.len <= 0 || uv_tcp->read_buf.base == NULL) {
        uv_tcp->read_buf.base = NULL; uv_tcp->read_buf.len = 0; uv_buf_t uv_buf = uv_tcp->read_buf;
        uv_tcp->uv_read_cb((uv_stream_t *)uv_tcp, UV_ENOBUFS, &uv_buf);
        return;
    }
loop:
    ;
    assert(uv_tcp->fd != -1);
    int ret = read(uv_tcp->fd, uv_tcp->read_buf.base, uv_tcp->read_buf.len);
    if (ret > 0) {
        uv_tcp->read_times++;
        ADD_UV_TCP_TO_READ_UV_TCP_TASKLIST(uv_tcp, 0);
        uv_buf_t uv_buf = uv_tcp->read_buf; uv_tcp->read_buf.base = NULL; uv_tcp->read_buf.len = 0;
        uv_tcp->uv_read_cb((uv_stream_t *)uv_tcp, ret, &uv_buf);
    } else if (ret < 0) {
        if (0) {
        } else if (errno == EAGAIN || errno == EWOULDBLOCK) {
            uv_tcp->epoll_say_readable = 0;
        } else if (errno == EINPROGRESS || errno == ENOTCONN) {
            LOGFEW("bug, fix me\n");
            ADD_UV_TCP_TO_READ_UV_TCP_TASKLIST(uv_tcp, 0);
        } else if (errno == EPIPE)                          {
            uv_tcp->is_remote_gone = 1;
            uv_buf_t uv_buf = uv_tcp->read_buf; uv_tcp->read_buf.base = NULL; uv_tcp->read_buf.len = 0;
            uv_tcp->uv_read_cb((uv_stream_t *)uv_tcp, UV_EPIPE, &uv_buf);
        } else if (errno == ECONNRESET || errno == ENOENT)  {
            uv_tcp->is_remote_gone = 1;
            uv_buf_t uv_buf = uv_tcp->read_buf; uv_tcp->read_buf.base = NULL; uv_tcp->read_buf.len = 0;
            uv_tcp->uv_read_cb((uv_stream_t *)uv_tcp, UV_ECONNRESET, &uv_buf);
        } else if (errno == ETIMEDOUT) {
            LOGFEW("wow, see read tcp ETIMEOUT\n");
            uv_tcp->is_remote_gone = 1;
            uv_buf_t uv_buf = uv_tcp->read_buf; uv_tcp->read_buf.base = NULL; uv_tcp->read_buf.len = 0;
            uv_tcp->uv_read_cb((uv_stream_t *)uv_tcp, UV_ETIMEDOUT, &uv_buf);
        } else if (errno == EINTR) { goto loop;
        } else {
            uv_tcp->is_remote_gone = 1;
            uv_buf_t uv_buf = uv_tcp->read_buf; uv_tcp->read_buf.base = NULL; uv_tcp->read_buf.len = 0;
            uv_tcp->uv_read_cb((uv_stream_t *)uv_tcp, UV_UNKNOWN, &uv_buf);
            LOGFEW("fix me[%m]\n");
        }
    } else if (ret == 0) {
        uv_buf_t uv_buf = uv_tcp->read_buf; uv_tcp->read_buf.base = NULL; uv_tcp->read_buf.len = 0;
        uv_tcp->uv_read_cb((uv_stream_t *)uv_tcp, UV_EOF, &uv_buf);
    }
}

void _read_uv_udp(uv_udp_t *uv_udp)
{
    if (is_in_list(&uv_udp->read_node)) list_del(&uv_udp->read_node);
    struct sockaddr addr = {0};
    if (uv_udp->is_close_called) {
        if (uv_udp->read_buf.base && uv_udp->read_buf.len > 0) {
            uv_buf_t uv_buf = uv_udp->read_buf; uv_udp->read_buf.base = NULL; uv_udp->read_buf.len = 0;
            uv_udp->uv_udp_recv_cb(uv_udp, UV_ECANCELED, &uv_buf, &addr, 0);
        }
        return;
    }
    if (uv_udp->is_read_stop) return;
    if (uv_udp->read_buf.len <= 0 || uv_udp->read_buf.base == NULL) { uv_udp->uv_alloc_cb((uv_handle_t *)uv_udp, 32000, &uv_udp->read_buf); }
    if (uv_udp->read_buf.len <= 0 || uv_udp->read_buf.base == NULL) {
        uv_udp->read_buf.base = NULL; uv_udp->read_buf.len = 0; uv_buf_t uv_buf = uv_udp->read_buf;
        uv_udp->uv_udp_recv_cb(uv_udp, UV_ENOBUFS, &uv_buf, &addr, 0);
        return;
    }
    socklen_t addr_len = 0;
    assert(uv_udp->fd != -1);
loop:
    ;
    int ret = recvfrom(uv_udp->fd, uv_udp->read_buf.base, uv_udp->read_buf.len, MSG_DONTWAIT, &addr, &addr_len);
    if (ret > 0) {
        uv_udp->read_times++;
        ADD_UV_UDP_TO_READ_UV_UDP_TASKLIST(uv_udp);
        uv_buf_t uv_buf = uv_udp->read_buf; uv_udp->read_buf.base = NULL; uv_udp->read_buf.len = 0;
        uv_udp->uv_udp_recv_cb(uv_udp, ret, &uv_buf, &addr, 0); }
    else if (errno == EAGAIN || errno == EINPROGRESS || errno == ENOTCONN) { }
    else if (errno == EINTR) { goto loop; }
    else { LOGFEW("fix me\n"); }
}

static inline int uv_read_start(uv_stream_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb)
{
    if (handle->type == UV_TYPE_TCP) {
        uv_tcp_t *uv_tcp = (uv_tcp_t *)handle;
        uv_tcp->uv_alloc_cb = alloc_cb;
        uv_tcp->uv_read_cb = read_cb;
        uv_tcp->is_read_stop = 0;
        ADD_UV_TCP_TO_READ_UV_TCP_TASKLIST(uv_tcp, 0);
    } else {
        LOGDIE("dddddddddd\n");
    }
    return 0;
}

static inline int uv_read_stop(uv_stream_t* handle)
{
    if (handle->type == UV_TYPE_TCP) {
        uv_tcp_t *uv_tcp = (uv_tcp_t *)handle;
        uv_tcp->is_read_stop = 1;
    } else {
        LOGDIE("dddddddddddddddddddd\n");
    }
    return 0;
}

static inline int uv_udp_recv_stop(uv_udp_t* uv_udp) { uv_udp->is_read_stop = 1; return 0; }

static inline int uv_tcp_bind(uv_tcp_t* uv_tcp, const struct sockaddr* addr, unsigned int flags)
{
    if (uv_tcp->fd <= 0) {
        int new_fd = socket(AF_INET, SOCK_STREAM, 0); if (new_fd < 0) { LOGFEW("socket error[%m]\n"); return UV_UNKNOWN; }
        _uv_tcp_set_fd(uv_tcp->loop, uv_tcp, new_fd, EPOLLET | EPOLLIN | EPOLLOUT);
    }
    if (addr) {
        int _i = 1; setsockopt(uv_tcp->fd, SOL_SOCKET ,SO_REUSEADDR, &_i,sizeof(_i));
        int ret = bind(uv_tcp->fd, addr, sizeof(struct sockaddr_in));
        if (ret == 0) { uv_tcp->is_finish_handshake = 1; }
        else if (errno == EADDRINUSE) { return UV_EADDRINUSE; }
        else { LOGDIE("dddddddddd\n"); }
    }
    return 0;
}

static inline int uv_tcp_close_reset(uv_tcp_t* uv_tcp, uv_close_cb uv_close_cb)                                                { LOGDIE("dddddddddd\n"); return 0; }
#define uv_udp_connect(uv_udp, addr) ({\
    int _ret = -1;\
    if ((uv_udp)->fd < 0) {\
        int _new_fd = socket(AF_INET, SOCK_DGRAM, 0); \
        if (_new_fd < 0) LOGFEW("socket() error[%m]\n"); else _uv_udp_set_fd((uv_udp)->loop, uv_udp, _new_fd, EPOLLET | EPOLLIN);\
    }\
    if ((uv_udp)->fd >= 0) { \
        _ret = connect((uv_udp)->fd, addr, sizeof(struct sockaddr_in)); /*if (_ret) LOGFEW("connect() error[%m]\n"); */\
    }\
    _ret; })

#define uv_tcp_connect(__uv_connect, uv_tcp, addr, __uv_connect_cb) ({ \
    uv_connect_t* _uv_connect = __uv_connect; uv_tcp_t* _uv_tcp = uv_tcp; const struct sockaddr* _addr = addr; \
    if (_uv_tcp->uv_connect) LOGDIE("dddddddddddddddd\n"); \
    _uv_tcp->uv_connect = _uv_connect; \
    _uv_connect->uv_connect_cb = __uv_connect_cb; \
    int _ret = UV_UNKNOWN; \
    if (_uv_tcp->fd < 0) { \
        int new_fd = socket(AF_INET, SOCK_STREAM, 0); if (new_fd < 0) { LOGFEW("socket error[%m]\n"); } \
        else _uv_tcp_set_fd(_uv_tcp->loop, uv_tcp, new_fd, EPOLLET | EPOLLIN | EPOLLOUT); \
    } \
    if (_uv_tcp->fd >= 0) { \
        _ret = connect(_uv_tcp->fd, _addr, sizeof(struct sockaddr_in)); \
        if (_ret == 0) { _uv_tcp->is_finish_handshake = 1; ADD_UV_TCP_TO_WRITE_UV_TCP_TASKLIST(_uv_tcp); __uv_connect_cb(_uv_connect, 0); } \
        else if (errno == EINPROGRESS) { _uv_tcp->is_connecting = 1; _ret = 0; } \
        else if (errno == ENETUNREACH) { _ret = UV_ENETUNREACH;; } \
        else { LOGFEW("bug, fix me [%m]\n"); _ret = UV_ECONNREFUSED; } \
    } \
    _ret; })

#define uv_tcp_getpeername(uv_stream, name, namelen) ({ \
        int _fd = -1; \
        int _ret = UV_UNKNOWN; \
        socklen_t _socklen = *(namelen); \
        if (0) { \
        } else if ((uv_stream)->type == UV_TYPE_TCP) { uv_tcp_t *_uv_tcp = (uv_tcp_t *)uv_stream; _fd = _uv_tcp->fd; \
        } else if ((uv_stream)->type == UV_TYPE_UDP) { uv_udp_t *_uv_udp = (uv_udp_t *)uv_stream; _fd = _uv_udp->fd; assert(_uv_udp->fd != -1); \
        } else { LOGFEW("can not handle type %d, bug, fix me\n", (uv_stream)->type); \
        } \
        if (_fd >= 0) { if (getpeername(_fd, name, &_socklen) == 0) _ret = 0; else LOGFEW("attation: getpeername for %d return [%m]\n", _fd); } \
        *namelen = _socklen; _ret; })

static inline int uv_tcp_getsockname(const uv_tcp_t* uv_tcp, struct sockaddr* name, int* namelen)
{
    socklen_t socklen = *namelen;
    int ret = getsockname(uv_tcp->fd, name, &socklen); if (ret) LOGDIE("dddddddddddddd\n");
    *namelen = socklen;
    return 0;
}

#define _check_and_do_shutdown(uv_tcp) do { \
    if ((uv_tcp)->uv_shutdown_req &&(uv_tcp)->is_finish_handshake && (uv_tcp)->is_close_called == 0 && list_empty(&uv_tcp->write_req_list)) { \
        int _ret = shutdown((uv_tcp)->fd, SHUT_WR); \
        if (_ret) { \
            _ret = UV_UNKNOWN; \
            if (0) { \
            } else if (errno == ENOTCONN) { _ret = UV_ENOTCONN; \
            } else { LOGFEW("shutdow %d error[%m]\n", (uv_tcp)->fd); \
            } \
        } \
        uv_shutdown_t *uv_shutdown_req = (uv_tcp)->uv_shutdown_req; (uv_tcp)->uv_shutdown_req = NULL; \
        uv_shutdown_req->uv_shutdown_cb(uv_shutdown_req, _ret); \
    } \
} while(0)

static inline void _write_uv_tcp(uv_tcp_t *uv_tcp)
#define _write_uv_tcp(uv_tcp) do { LOGMSG("calling _write_uv_tcp\n"); _write_uv_tcp(uv_tcp); } while(0)
{
    if (is_in_list(&uv_tcp->write_node)) list_del(&uv_tcp->write_node);
loop:
    if (list_empty(&uv_tcp->write_req_list)) goto out;
    uv_write_t *uv_write = list_first_entry(&uv_tcp->write_req_list, uv_write_t, node);
    if (uv_tcp->is_close_called) {
        list_del(&uv_write->node);
        uv_write->uv_write_cb(uv_write, UV_ECANCELED);
        goto loop;
    }
    if (uv_write->buf_count != 1) LOGDIE("bug, fix me\n");
    if (uv_tcp->is_finish_handshake == 0) goto out;
    if (uv_tcp->is_remote_gone) goto out;
    const uv_buf_t *uv_buf = uv_write->buf;
    assert(uv_tcp->fd != -1);
send_loop:
    ;
    int ret = send(uv_tcp->fd, uv_buf->base + uv_write->writed_len, uv_buf->len - uv_write->writed_len, MSG_NOSIGNAL);
    if (ret > 0) {
        ADD_UV_TCP_TO_WRITE_UV_TCP_TASKLIST(uv_tcp); 
        uv_write->writed_len += ret; if (uv_write->writed_len == uv_buf->len) { list_del(&uv_write->node); uv_write->uv_write_cb(uv_write, 0); } 
        _check_and_do_shutdown(uv_tcp);
    } else if (errno == EAGAIN    ) { goto out;
    } else if (errno == EPIPE     ) { uv_tcp->is_remote_gone = 1; list_del(&uv_write->node); uv_write->uv_write_cb(uv_write, UV_EPIPE);
    } else if (errno == ECONNRESET) { uv_tcp->is_remote_gone = 1; list_del(&uv_write->node); uv_write->uv_write_cb(uv_write, UV_ECONNRESET);
    } else if (errno == ENOENT    ) { uv_tcp->is_remote_gone = 1; list_del(&uv_write->node); uv_write->uv_write_cb(uv_write, UV_ENOENT);
    } else if (errno == EINTR     ) { goto send_loop;
    } else if (errno == ETIMEDOUT ) { uv_tcp->is_remote_gone = 1; list_del(&uv_write->node); uv_write->uv_write_cb(uv_write, UV_ETIMEDOUT);
    } else                          { uv_tcp->is_remote_gone = 1; list_del(&uv_write->node); uv_write->uv_write_cb(uv_write, UV_UNKNOWN); LOGFEW("write to fd %d return %d[%m]\n", uv_tcp->fd, ret); }

out:
    return;
}

static inline void _write_uv_udp(uv_udp_t *uv_udp)
//#define _write_uv_udp(uv_udp) do { LOGMSG("calling _write_uv_udp\n"); _write_uv_udp(uv_udp); } while(0)
{
    int ret = 0;
    if (is_in_list(&uv_udp->write_node)) list_del(&uv_udp->write_node);
loop1:
    if (list_empty(&uv_udp->write_req_list)) goto out;
    uv_udp_send_t *uv_udp_send = list_first_entry(&uv_udp->write_req_list, uv_udp_send_t, node);
    if (uv_udp_send->buf_count != 1) LOGDIE("bug, fix me\n");
    if (uv_udp->is_close_called) {
        list_del(&uv_udp_send->node);
        uv_udp_send->uv_udp_send_cb(uv_udp_send, UV_ECANCELED);
        goto loop1;
    }
    const uv_buf_t *uv_buf = uv_udp_send->buf;
    if (uv_udp->fd < 0) {
        int new_fd = socket(AF_INET, SOCK_DGRAM, 0); if (new_fd < 0) { LOGFEW("socket() error[%m]\n"); goto err; }
        _uv_udp_set_fd(uv_udp->loop, uv_udp, new_fd, EPOLLET | EPOLLIN);
    }
    int try_count = 0;
loop:
    try_count++;
    if (uv_udp_send->is_addr_valid) {
        ret = sendto(uv_udp->fd, uv_buf->base, uv_buf->len, 0, &uv_udp_send->addr, sizeof(struct sockaddr_in));
    } else {
        ret = send(uv_udp->fd, uv_buf->base, uv_buf->len, 0);
    }
    if (ret > 0)                      {
        ADD_UV_UDP_TO_WRITE_UV_UDP_TASKLIST(uv_udp); 
        list_del(&uv_udp_send->node); uv_udp_send->uv_udp_send_cb(uv_udp_send, 0); if (ret != uv_buf->len) LOGDIE("ddddddddddddddddd\n");
    } else if (errno == EAGAIN      ) {
        if (try_count >= 2) {
            list_del(&uv_udp_send->node); uv_udp_send->uv_udp_send_cb(uv_udp_send, UV_UNKNOWN);
            LOGFEW("write to fd %d return %d[errno %d %m]\n", uv_udp->fd, ret, errno);
            goto out;
        }
        goto loop;
    } else if (errno == EINTR       ) { goto loop;
    } else if (errno == EPIPE       ) { list_del(&uv_udp_send->node); uv_udp_send->uv_udp_send_cb(uv_udp_send, UV_EPIPE);
    } else if (errno == ECONNRESET  ) { list_del(&uv_udp_send->node); uv_udp_send->uv_udp_send_cb(uv_udp_send, UV_ECONNRESET);
    } else if (errno == ECONNREFUSED) { list_del(&uv_udp_send->node); uv_udp_send->uv_udp_send_cb(uv_udp_send, UV_ECONNREFUSED);
    } else if (errno == ENOENT      ) { list_del(&uv_udp_send->node); uv_udp_send->uv_udp_send_cb(uv_udp_send, UV_ENOENT);
    } else if (errno == EHOSTUNREACH) { list_del(&uv_udp_send->node); uv_udp_send->uv_udp_send_cb(uv_udp_send, UV_EHOSTUNREACH);
    } else                            {
err:
        list_del(&uv_udp_send->node); uv_udp_send->uv_udp_send_cb(uv_udp_send, UV_UNKNOWN); LOGFEW("write to fd %d return %d[errno %d %m]\n", uv_udp->fd, ret, errno); }

out:
    return;
}

static inline int uv_write(uv_write_t* req, uv_stream_t* handle, const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb uv_write_cb)
{
    if (nbufs != 1) LOGDIE("bug, fix me\n");
    memset(req, 0, sizeof(*req));
    req->uv_write_cb = uv_write_cb;
    req->writed_len = 0;
    if (handle->type == UV_TYPE_TCP) {
        uv_tcp_t *uv_tcp = (uv_tcp_t *)handle;
        if (uv_tcp->is_close_called) LOGDIE("ddddddddddddddddd\n");
        req->buf = bufs;
        req->buf_count = nbufs;
        list_add_tail(&req->node, &uv_tcp->write_req_list);
        ADD_UV_TCP_TO_WRITE_UV_TCP_TASKLIST(uv_tcp);
    } else if (handle->type == UV_TYPE_UDP) {
        uv_udp_t *uv_udp = (uv_udp_t *)handle;
        assert(uv_udp->fd != -1);
        int ret = write(uv_udp->fd, bufs[0].base, bufs[0].len); if (ret != bufs[0].len) LOGDIE("ddddddddddd\n");
        uv_write_cb(req, 0);
    } else {
        LOGDIE("dddddddddddd type %d", handle->type);
    }
    return 0;
}

void UPDATE_TIMEOUT_VAL(struct timespec *ts, int interval)
{
    clock_gettime(CLOCK_REALTIME, ts);
    ts->tv_sec += interval / 1000;
    ts->tv_nsec += (interval % 1000) * 1000000;
    if (ts->tv_nsec >= 1000000000) {
        ts->tv_nsec -= 1000000000;
        ts->tv_sec++;
    }
}

void *_uv_timeout_thread(void *arg)
{
    uv_loop_t *uv_loop = arg;
    for (;;) {
        if (sleep(1)) continue;
loop:
        if (write(uv_loop->uv_timeout.pipes[1], "1", 1) != 1) {
            if (0) { }
            else if (errno == EAGAIN) { }
            else if (errno == EINTR) { goto loop; }
            else { LOGDIE("dddddddddd\n"); }
        }
    }
}

int _uv_getaddrinfo_translate_error(int sys_err) {
    switch (sys_err) {
        case 0: return 0;
#if defined(EAI_ADDRFAMILY)
        case EAI_ADDRFAMILY: return UV_EAI_ADDRFAMILY;
#endif
#if defined(EAI_AGAIN)
        case EAI_AGAIN: return UV_EAI_AGAIN;
#endif
#if defined(EAI_BADFLAGS)
        case EAI_BADFLAGS: return UV_EAI_BADFLAGS;
#endif
#if defined(EAI_BADHINTS)
        case EAI_BADHINTS: return UV_EAI_BADHINTS;
#endif
#if defined(EAI_CANCELED)
        case EAI_CANCELED: return UV_EAI_CANCELED;
#endif
#if defined(EAI_FAIL)
        case EAI_FAIL: return UV_EAI_FAIL;
#endif
#if defined(EAI_FAMILY)
        case EAI_FAMILY: return UV_EAI_FAMILY;
#endif
#if defined(EAI_MEMORY)
        case EAI_MEMORY: return UV_EAI_MEMORY;
#endif
#if defined(EAI_NODATA)
        case EAI_NODATA: return UV_EAI_NODATA;
#endif
#if defined(EAI_NONAME)
# if !defined(EAI_NODATA) || EAI_NODATA != EAI_NONAME
        case EAI_NONAME: return UV_EAI_NONAME;
# endif
#endif
#if defined(EAI_OVERFLOW)
        case EAI_OVERFLOW: return UV_EAI_OVERFLOW;
#endif
#if defined(EAI_PROTOCOL)
        case EAI_PROTOCOL: return UV_EAI_PROTOCOL;
#endif
#if defined(EAI_SERVICE)
        case EAI_SERVICE: return UV_EAI_SERVICE;
#endif
#if defined(EAI_SOCKTYPE)
        case EAI_SOCKTYPE: return UV_EAI_SOCKTYPE;
#endif
#if defined(EAI_SYSTEM)
        case EAI_SYSTEM: return UV_ERR(errno);
#endif
    }
    assert(!"unknown EAI_* error code");
    abort();
    return 0;
}

#define HAVE_UV_TCP_STAT 1
int uv_tcp_stat(uv_tcp_t *uv_tcp, char *buf, int buf_len)
{
    int len = 0;
    len += snprintf(buf + len, buf_len - len, "is_writeing %d ", is_in_list(&uv_tcp->write_node)); if (len > buf_len) len = buf_len;
    return len;
}

#define HAVE_UV_STAT 1
int uv_stat(uv_loop_t *uv_loop, char *buf, int buf_len)
{
    int len = 0;
    pthread_mutex_lock(&uv_loop->getaddrinfo_lock);
    len += snprintf(buf + len, buf_len - len, "getaddrinfo_task [tasklist_len %u max %u total %u] getaddinfo_thread [create %u count %u max %u bingfa_allow_max %u]",
            uv_loop->getaddrinfo_tasklist_len, uv_loop->getaddrinfo_tasklist_len_max, uv_loop->getaddrinfo_task_total,
            uv_loop->getaddrinfo_thread_create_count, uv_loop->getaddrinfo_thread_count, uv_loop->getaddrinfo_thread_count_max, UV_GETADDRINFO_BINGFA_MAX);
    if (len >= buf_len) len = buf_len - 1;
    buf[len] = 0;
    pthread_mutex_unlock(&uv_loop->getaddrinfo_lock);
    return len;
}

void *_uv_getaddrinfo_thread(void *arg)
{
    uv_loop_t *uv_loop = arg;
    uv_getaddrinfo_t *task;
    pthread_detach(pthread_self());

    for (;;) {
        task = NULL;
        pthread_mutex_lock(&uv_loop->getaddrinfo_lock);
        uv_loop->getaddrinfo_thread_busy--;
        if (list_empty(&uv_loop->getaddrinfo_tasklist)) {
            if (uv_loop->getaddrinfo_thread_count > 32) {
                uv_loop->getaddrinfo_thread_count--;
                pthread_mutex_unlock(&uv_loop->getaddrinfo_lock);
                break;
            }
            if (uv_loop->closed) {
                uv_loop->getaddrinfo_thread_count--;
                pthread_mutex_unlock(&uv_loop->getaddrinfo_lock);
                break;
            }
            struct timespec ts;
            clock_gettime(CLOCK_REALTIME, &ts);
            ts.tv_sec++;
            pthread_cond_timedwait(&uv_loop->getaddrinfo_cond, &uv_loop->getaddrinfo_lock, &ts);
        } else {
            task = list_first_entry(&uv_loop->getaddrinfo_tasklist, uv_getaddrinfo_t, node);
            list_del(&task->node); uv_loop->getaddrinfo_tasklist_len--;
            uv_loop->getaddrinfo_thread_busy++;

            pthread_t pid;
            if (uv_loop->getaddrinfo_tasklist_len > 0 && uv_loop->getaddrinfo_thread_busy >= uv_loop->getaddrinfo_thread_count && uv_loop->getaddrinfo_thread_count < UV_GETADDRINFO_BINGFA_MAX) {
                uv_loop->getaddrinfo_thread_busy++;
                uv_loop->getaddrinfo_thread_count++;
                uv_loop->getaddrinfo_thread_create_count++;
                if (pthread_create(&pid, NULL, _uv_getaddrinfo_thread, uv_loop) != 0) {
                    uv_loop->getaddrinfo_thread_busy--;
                    uv_loop->getaddrinfo_thread_count--;
                    uv_loop->getaddrinfo_thread_create_count--;
                } else {
                    if (uv_loop->getaddrinfo_thread_count_max < uv_loop->getaddrinfo_thread_count) uv_loop->getaddrinfo_thread_count_max = uv_loop->getaddrinfo_thread_count;
                }
            }
        }
        pthread_mutex_unlock(&uv_loop->getaddrinfo_lock);
        if (task) {
            int ret = muslgetaddrinfo(task->hostname, task->service, &task->hints, &task->addrinfo);
            task->retcode = _uv_getaddrinfo_translate_error(ret);

            pthread_mutex_lock(&uv_loop->getaddrinfo_resultlist_lock);
            list_add_tail(&task->node, &uv_loop->getaddrinfo_resultlist);
            pthread_mutex_unlock(&uv_loop->getaddrinfo_resultlist_lock);
loop:
            if (write(uv_loop->uv_getaddrinfo_result.pipes[1], "1", 1) != 1) {
                if (0) {
                } else if (errno == EAGAIN) {
                } else if (errno == EINTR ) { goto loop;
                } else { LOGDIE("dddddddddd\n");
                }
            }
        }
    }
    return NULL;
}

void _uv_close(uv_handle_t *handle)
{
    list_del(&handle->close_node); 
    if (0) {
    } else if (handle->type == UV_TYPE_TCP) { uv_tcp_t *uv_tcp = (uv_tcp_t *)handle; _read_uv_tcp(uv_tcp); _write_uv_tcp(uv_tcp); assert(list_empty(&uv_tcp->write_req_list));
    } else if (handle->type == UV_TYPE_UDP) { uv_udp_t *uv_udp = (uv_udp_t *)handle; _read_uv_udp(uv_udp); _write_uv_udp(uv_udp); assert(list_empty(&uv_udp->write_req_list));
    } else if (handle->type == UV_TYPE_IDLE) {
    } else if (handle->type == UV_TYPE_TIMER) {
    } else if (handle->type == UV_TYPE_ASYNC) { LOGDIE("bug, fix me\n");
    } else { LOGDIE("bug, fix me[type %d %s]\n", handle->type, _uv_type_to_name(handle->type));
    }
    uv_close_cb uv_close_cb = handle->uv_close_cb; handle->uv_close_cb = NULL;
    uv_close_cb(handle);
}

static inline void uv_close(uv_handle_t* handle, uv_close_cb cb)
//#define            uv_close(handle, cb) do {
{
    if ((handle)->uv_close_cb)     { LOGDIE("bug, fix me\n"); } (handle)->uv_close_cb = cb; \
    if ((handle)->is_close_called) { LOGDIE("bug, fix me\n"); } (handle)->is_close_called = 1; \
    if ((handle)->is_in_epoll_out_list) { list_del(&(handle)->node_for_epoll_out); (handle)->is_in_epoll_out_list = 0; } \
    if (0) { \
    } else if ((handle)->type == UV_TYPE_TCP) { uv_tcp_t *uv_tcp = (uv_tcp_t *)(handle); \
        if (uv_tcp->fd >= 0) { epoll_ctl((handle)->loop->epoll_fd, EPOLL_CTL_DEL, uv_tcp->fd, NULL); close(uv_tcp->fd); uv_tcp->fd = -1; } \
        if (uv_tcp->accepted_fd >= 0) { close(uv_tcp->accepted_fd); uv_tcp->accepted_fd = -1; } \
    } else if ((handle)->type == UV_TYPE_UDP) { uv_udp_t *uv_udp = (uv_udp_t *)(handle); \
        if (uv_udp->fd >= 0) { epoll_ctl((handle)->loop->epoll_fd, EPOLL_CTL_DEL, uv_udp->fd, NULL); close(uv_udp->fd); uv_udp->fd = -1; } \
    } else if ((handle)->type == UV_TYPE_TIMER) { uv_timer_t *uv_timer = (uv_timer_t *)(handle); if (is_in_list(&uv_timer->node)) list_del(&uv_timer->node); \
    } else if ((handle)->type == UV_TYPE_IDLE)  { uv_idle_t  *uv_idle  = (uv_idle_t  *)(handle); if (is_in_list(&uv_idle->node )) list_del(&uv_idle->node ); \
    } else { LOGERR("bug, fix me\n"); \
    } \
    list_add_tail(&(handle)->close_node, &(handle)->loop->close_tasklist); \
}

#define uv_ip4_addr(ipstr, port, addr) ({ \
        int _ret = 0; \
        uint32_t _ip; \
        if (inet_pton(AF_INET, (ipstr), &_ip) != 1) { LOGFEW("illigle ipstr [%s]\n", ipstr); _ret = -1; } \
        if (_ret == 0) { \
            memset(addr, 0, sizeof(*(addr))); \
            (addr)->sin_family = AF_INET; \
            (addr)->sin_addr.s_addr = _ip; \
            (addr)->sin_port = htons(port); \
        } \
        _ret; })

//static inline int uv_ip6_addr(const char* ip, int port, struct sockaddr_in6* addr)      { LOGDIE("ddddddddddddddd\n"); return 0; }
//static inline int uv_ip4_name(const struct sockaddr_in* src, char* dst, size_t size)    { LOGDIE("ddddddddddddddd\n"); return 0; }
//static inline int uv_ip6_name(const struct sockaddr_in6* src, char* dst, size_t size)   { LOGDIE("ddddddddddddddd\n"); return 0; }
//static inline int uv_ip_name(const struct sockaddr *src, char *dst, size_t size) {
//    switch (src->sa_family) {
//        case AF_INET:
//            return uv_inet_ntop(AF_INET, &((struct sockaddr_in *)src)->sin_addr,
//                    dst, size);
//        case AF_INET6:
//            return uv_inet_ntop(AF_INET6, &((struct sockaddr_in6 *)src)->sin6_addr,
//                    dst, size);
//        default:
//            return UV_EAFNOSUPPORT;
//    }
//}
//
//static inline int uv_inet_ntop(int af, const void* src, char* dst, size_t size) { return inet_ntop(af, src, dst, size); }
//static inline int uv_inet_pton(int af, const char* src, void* dst)              { return inet_pton(af, src, dst); }

//static inline int uv_getaddrinfo(uv_loop_t* uv_loop, uv_getaddrinfo_t* req, uv_getaddrinfo_cb uv_getaddrinfo_cb, const char* host, const char* service, const struct addrinfo* hints)
#define uv_getaddrinfo(uv_loop, req, uv_getaddrinfo_cb, host, __service, __hints) ({ \
        const char *_service = __service; \
        const struct addrinfo* _hints = __hints; \
    memset(req, 0, sizeof(*(req))); \
    (req)->cb = uv_getaddrinfo_cb; \
    if (host) { (req)->hostname = strdup(host); if ((req)->hostname == NULL) LOGDIE("dddddddddddddddd\n"); } \
    if (_service && _service[0]) { (req)->service = strdup(_service);  if ((req)->service == NULL) LOGDIE("dddddddddddddddd\n"); } \
    if (_hints) (req)->hints = *(_hints); \
    pthread_mutex_lock(&(uv_loop)->getaddrinfo_lock); \
    list_add_tail(&(req)->node, &(uv_loop)->getaddrinfo_tasklist); \
    (uv_loop)->getaddrinfo_tasklist_len++; \
    (uv_loop)->getaddrinfo_task_total++; \
    if ((uv_loop)->getaddrinfo_tasklist_len_max < (uv_loop)->getaddrinfo_tasklist_len) (uv_loop)->getaddrinfo_tasklist_len_max = (uv_loop)->getaddrinfo_tasklist_len; \
    pthread_mutex_unlock(&(uv_loop)->getaddrinfo_lock); \
    pthread_cond_signal(&(uv_loop)->getaddrinfo_cond); \
    0; })

#define uv_tcp_nodelay(handle, enable) ({ SETNODELAY((handle)->fd, enable); 0; })
static inline int set_tcp_keepAlive(int fd, int start, int interval, int count)
{
    int turn = 1;
    if (fd < 0 || start < 0 || interval < 0 || count < 0) return -1;
    if(setsockopt(fd,SOL_SOCKET,SO_KEEPALIVE,(void*)&turn,sizeof(turn)) == -1) { perror("setsockopt"); return -1; }
    if(setsockopt(fd,SOL_TCP,TCP_KEEPIDLE,(void *)&start,sizeof(start)) == -1) { perror("setsockopt"); return -1; }
    if(setsockopt(fd,SOL_TCP,TCP_KEEPINTVL,(void *)&interval,sizeof(interval)) == -1) { perror("setsockopt"); return -1; }
    if(setsockopt(fd,SOL_TCP,TCP_KEEPCNT,(void *)&count,sizeof(count)) == -1) { perror("setsockopt"); return -1; }
    return 0;
}

static inline int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay)
{
    if (enable) set_tcp_keepAlive(handle->fd, delay, delay, 3);
    return 0;
}

#define uv_loop_init(uv_loop) ({ \
    int _ret = 0; \
    struct sigaction sa = { .sa_handler = SIG_IGN }; sigaction(SIGPIPE, &sa, 0); \
    if ((uv_loop)->is_inited == IS_INITED_TAG) { LOGDIE("uv_loop_init double!!\n"); } \
    memset((uv_loop), 0, sizeof(*(uv_loop))); \
    (uv_loop)->is_inited = IS_INITED_TAG; \
    (uv_loop)->epoll_fd = epoll_create(1); if ((uv_loop)->epoll_fd < 0) { LOGDIE("dddddddddddddd\n"); } \
    INIT_LIST_HEAD(&(uv_loop)->child_list); pthread_mutex_init(&(uv_loop)->child_lock, NULL); \
    pthread_mutex_init(&(uv_loop)->getaddrinfo_lock, NULL); pthread_cond_init(&(uv_loop)->getaddrinfo_cond, NULL); \
    pthread_mutex_init(&(uv_loop)->getaddrinfo_resultlist_lock, NULL); \
    INIT_LIST_HEAD(&(uv_loop)->getaddrinfo_tasklist); \
    INIT_LIST_HEAD(&(uv_loop)->getaddrinfo_resultlist); \
    INIT_LIST_HEAD(&(uv_loop)->write_uv_tcp_tasklist); \
    INIT_LIST_HEAD(&(uv_loop)->read_uv_tcp_tasklist); \
    INIT_LIST_HEAD(&(uv_loop)->close_tasklist); \
    INIT_LIST_HEAD(&(uv_loop)->read_uv_udp_tasklist); \
    INIT_LIST_HEAD(&(uv_loop)->write_uv_udp_tasklist); \
    INIT_LIST_HEAD(&(uv_loop)->timer_list); \
    INIT_LIST_HEAD(&(uv_loop)->idle_list); \
    { int ret = pipe2((uv_loop)->uv_timeout.pipes, O_NONBLOCK); if (ret) { LOGDIE("dddddddddddddddd\n"); } } \
    { int ret = pipe2((uv_loop)->uv_getaddrinfo_result.pipes, O_NONBLOCK); if (ret) { LOGDIE("dddddddddddddddd\n"); } } \
    UV_EPOLL_ADD((uv_loop)->epoll_fd, (uv_loop)->uv_timeout.pipes[0], EPOLLET | EPOLLIN, &(uv_loop)->uv_timeout); \
    UV_EPOLL_ADD((uv_loop)->epoll_fd, (uv_loop)->uv_getaddrinfo_result.pipes[0], EPOLLET | EPOLLIN, &(uv_loop)->uv_getaddrinfo_result); \
    _ret = pthread_create(&(uv_loop)->timeout_pid, NULL, _uv_timeout_thread, (uv_loop)); assert(_ret == 0); \
    (uv_loop)->getaddrinfo_thread_busy = 1; \
    (uv_loop)->getaddrinfo_thread_count = 1; \
    (uv_loop)->getaddrinfo_thread_count_max = 1; \
    (uv_loop)->getaddrinfo_thread_create_count = 1; \
    pthread_t pid; \
    _ret = pthread_create(&pid, NULL, _uv_getaddrinfo_thread, (uv_loop)); assert(_ret == 0); \
    _ret; \
})

static inline int uv_loop_close(uv_loop_t* uv_loop)
{
    pthread_mutex_destroy(&uv_loop->getaddrinfo_lock);
    uv_loop->closed = 1;
    while (uv_loop->getaddrinfo_thread_count > 0) sleep(1);
    pthread_cond_destroy(&uv_loop->getaddrinfo_cond);
    pthread_mutex_destroy(&uv_loop->getaddrinfo_resultlist_lock);
    pthread_cancel(uv_loop->timeout_pid);
    assert(list_empty(&uv_loop->getaddrinfo_tasklist));
    assert(list_empty(&uv_loop->getaddrinfo_resultlist));
    assert(list_empty(&uv_loop->write_uv_tcp_tasklist));
    assert(list_empty(&uv_loop->read_uv_tcp_tasklist));
    assert(list_empty(&uv_loop->close_tasklist));
    assert(list_empty(&uv_loop->read_uv_udp_tasklist));
    assert(list_empty(&uv_loop->write_uv_udp_tasklist));
    assert(list_empty(&uv_loop->timer_list));
    assert(list_empty(&uv_loop->idle_list));
    close(uv_loop->uv_timeout.pipes[0]);
    close(uv_loop->uv_timeout.pipes[1]);
    close(uv_loop->uv_getaddrinfo_result.pipes[0]);
    close(uv_loop->uv_getaddrinfo_result.pipes[1]);

    pthread_mutex_lock(&uv_loop->parent->child_lock); list_del(&uv_loop->node); uv_loop->parent->child_count--; pthread_mutex_unlock(&uv_loop->parent->child_lock);

    //ret = pthread_create(&pid, NULL, _uv_getaddrinfo_thread, uv_loop); assert(ret == 0);
    close(uv_loop->epoll_fd);
    free(uv_loop);
    return 0;
}
void uv_freeaddrinfo(struct addrinfo* ai) { if (ai) muslfreeaddrinfo(ai); }

static inline int uv_udp_send(uv_udp_send_t* req, uv_udp_t* uv_udp, const uv_buf_t bufs[], unsigned int nbufs, const struct sockaddr* addr, uv_udp_send_cb uv_udp_send_cb)
{
    if (nbufs != 1) LOGDIE("ddddddddddddd\n");
    if (uv_udp->is_close_called) LOGDIE("ddddddddddddddddd\n");
    req->buf = bufs;
    req->buf_count = nbufs;
    req->uv_udp_send_cb = uv_udp_send_cb;
    if (addr) {
        req->addr = *addr;
        req->is_addr_valid = 1;
    } else {
        req->is_addr_valid = 0;
    }
    list_add_tail(&req->node, &uv_udp->write_req_list);
    ADD_UV_UDP_TO_WRITE_UV_UDP_TASKLIST(uv_udp);
    return 0;
}

static inline int uv_timer_init(uv_loop_t* uv_loop, uv_timer_t* uv_timer)
{
    memset(uv_timer, 0, sizeof(*uv_timer));
    uv_timer->type = UV_TYPE_TIMER;
    uv_timer->loop = uv_loop;
    return 0;
}

static inline int uv_idle_init(uv_loop_t* uv_loop, uv_idle_t* uv_idle)
{
    memset(uv_idle, 0, sizeof(*uv_idle));
    uv_idle->type = UV_TYPE_IDLE;
    uv_idle->loop = uv_loop;
    return 0;
}

static inline int uv_timer_start(uv_timer_t* handle, uv_timer_cb cb, uint64_t first_interval, uint64_t interval)
{
    UPDATE_TIMEOUT_VAL(&handle->timeout, first_interval);
    handle->interval = interval;
    handle->cb = cb;
    list_add_tail(&handle->node, &handle->loop->timer_list);
    return 0;
}

static inline int uv_idle_start(uv_idle_t* handle, uv_idle_cb cb)
{
    handle->cb = cb;
    assert(is_in_list(&handle->node) == 0);
    list_add_tail(&handle->node, &handle->loop->idle_list);
    return 0;
}

static inline int uv_idle_stop(uv_idle_t *handle)
{
    if (is_in_list(&handle->node)) list_del(&handle->node);
    return 0;
}

static inline int uv_timer_stop(uv_timer_t* handle) { LOGDIE("ddddddddddddddd\n"); return 0; }
static inline int uv_timer_again(uv_timer_t* handle) { LOGDIE("ddddddddddddddd\n"); return 0; }
static inline int uv_udp_recv_start(uv_udp_t* uv_udp, uv_alloc_cb uv_alloc_cb, uv_udp_recv_cb uv_udp_recv_cb)
{
    uv_udp->uv_alloc_cb = uv_alloc_cb;
    uv_udp->uv_udp_recv_cb = uv_udp_recv_cb;
    uv_udp->is_read_stop = 0;
    ADD_UV_UDP_TO_READ_UV_UDP_TASKLIST(uv_udp);
    return 0;
}

static inline void uv_shutdown(uv_shutdown_t* req, uv_stream_t* uv_stream, uv_shutdown_cb cb)
{
    (req)->uv_shutdown_cb = cb; \
    if ((uv_stream)->type == UV_TYPE_TCP) { \
        uv_tcp_t *uv_tcp = (uv_tcp_t *)(uv_stream); assert(uv_tcp->uv_shutdown_req == NULL); \
        uv_tcp->uv_shutdown_req = req; \
        _check_and_do_shutdown(uv_tcp); \
    } else { \
        LOGDIE("ddddddddddddddd\n"); \
    } \
}

static inline uv_buf_t uv_buf_init(char* base, unsigned int len) { uv_buf_t buf = { .base = base, .len = len }; return buf; }
#define uv_os_fd_t int
static inline int uv_fileno(const uv_handle_t* handle, uv_os_fd_t *fd)
{
    if (handle->type == UV_TYPE_TCP) {
        uv_tcp_t *uv_tcp = (uv_tcp_t *)handle;
        if (uv_tcp->fd <= 0) {
            int new_fd = socket(AF_INET, SOCK_STREAM, 0); if (new_fd < 0) { LOGFEW("socket error[%m]\n"); return UV_UNKNOWN; }
            _uv_tcp_set_fd(uv_tcp->loop, uv_tcp, new_fd, EPOLLET | EPOLLIN | EPOLLOUT);
        }
        *fd = uv_tcp->fd;
        return 0;
    } else if (handle->type == UV_TYPE_UDP) {
        uv_udp_t *uv_udp = (uv_udp_t *)handle;
        if (uv_udp->fd <= 0) {
            int new_fd = socket(AF_INET, SOCK_DGRAM, 0); if (new_fd < 0) { LOGFEW("socket error[%m]\n"); return UV_UNKNOWN; }
            _uv_udp_set_fd(uv_udp->loop, uv_udp, new_fd, EPOLLET | EPOLLIN);
        }
        *fd = uv_udp->fd;
        return 0;
    } else {
        LOGDIE("ddddddddddddddd\n"); \
    }
    return -1;
}

#define uv_udp_init(uv_loop, uv_udp) ({ \
    /*static int count = 0; count++; LOGINF("call uv_udp_init %u times\n", count);*/ \
    uv_loop_t * _uv_loop = uv_loop; \
    uv_udp_t * _uv_udp = uv_udp; \
    memset(_uv_udp, 0, sizeof(*_uv_udp)); \
    _uv_udp->type = UV_TYPE_UDP; \
    _uv_udp->loop = _uv_loop; \
    _uv_udp->fd = -1; \
    INIT_LIST_HEAD(&_uv_udp->write_req_list); \
    0; })

#define uv_tcp_init(uv_loop, uv_tcp) ({ \
    int _ret = -1; \
    /*static int count = 0; count++; LOGINF("call uv_tcp_init %u times\n", count);*/ \
    uv_loop_t* _uv_loop = uv_loop; \
    uv_tcp_t* _uv_tcp = uv_tcp; \
    memset(_uv_tcp, 0, sizeof(*_uv_tcp)); \
    _uv_tcp->type = UV_TYPE_TCP; \
    _uv_tcp->loop = _uv_loop; \
    _uv_tcp->accepted_fd = -1; \
    _uv_tcp->fd = -1; \
    INIT_LIST_HEAD(&_uv_tcp->write_req_list); \
    _ret; })

#define UV_EPOLL_EVENT_MAX 128
static inline int uv_run(uv_loop_t* uv_loop, uv_run_mode mode)
{
    uv_loop->mode = mode;
    int event_count, event_index;
    uv_tcp_t *uv_tcp;
    uv_udp_t *uv_udp;
    uv_async_t *uv_async;
    uv_handle_t *handle;
    int _uv_close_count = 0;
    struct timespec last_check_timeout_ts = {0};
    struct epoll_event events[UV_EPOLL_EVENT_MAX];

#define try_do_uv_close do { \
    while(list_empty(&uv_loop->close_tasklist) == 0) { _uv_close(list_first_entry(&uv_loop->close_tasklist, uv_handle_t, close_node)); _uv_close_count++; } } while(0)
    for (;;) {
        try_do_uv_close; list_for_each_entry(uv_tcp, &uv_loop->read_uv_tcp_tasklist, read_node)   { _read_uv_tcp(uv_tcp); break; }
        try_do_uv_close; list_for_each_entry(uv_udp, &uv_loop->read_uv_udp_tasklist, read_node)   { _read_uv_udp(uv_udp); break; }
        try_do_uv_close; list_for_each_entry(uv_tcp, &uv_loop->write_uv_tcp_tasklist, write_node) { _write_uv_tcp(uv_tcp); break; }
        try_do_uv_close; list_for_each_entry(uv_udp, &uv_loop->write_uv_udp_tasklist, write_node) { _write_uv_udp(uv_udp); break; }
        try_do_uv_close;
        int timeout = 100;
        if (list_empty(&uv_loop->read_uv_tcp_tasklist) == 0 || list_empty(&uv_loop->read_uv_udp_tasklist) == 0 || list_empty(&uv_loop->write_uv_tcp_tasklist) == 0 || list_empty(&uv_loop->write_uv_udp_tasklist) == 0) {
            timeout = 0;
        } else {
            if (uv_loop->mode == UV_RUN_ONCE && _uv_close_count) return 0;
        }

        //if (timeout) 
        {
            uv_idle_t *uv_idle = list_first_entry_or_null(&uv_loop->idle_list, uv_idle_t, node);
            if (uv_idle) {
                list_del(&uv_idle->node);
                list_add_tail(&uv_idle->node, &uv_loop->idle_list);
                uv_idle->cb(uv_idle);
                timeout = 0;
            }
        }
        event_count = epoll_wait(uv_loop->epoll_fd, events, UV_EPOLL_EVENT_MAX, timeout);
        {
            uv_timer_t *uv_timer, *n;
            struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts);
            uint64_t a = last_check_timeout_ts.tv_nsec - ts.tv_nsec;
            if (last_check_timeout_ts.tv_sec != ts.tv_sec || a >= 10000000) {
                last_check_timeout_ts = ts;
                list_for_each_entry_safe(uv_timer, n, &uv_loop->timer_list, node) {
                    if (uv_timer->timeout.tv_sec < ts.tv_sec || ( uv_timer->timeout.tv_sec == ts.tv_sec && uv_timer->timeout.tv_nsec <= ts.tv_nsec)) {
                        UPDATE_TIMEOUT_VAL(&uv_timer->timeout, uv_timer->interval);
                        uv_timer->cb(uv_timer);
                    }
                }
            }
        }
        if (event_count == 0) { /*LOGMSG("epoll_wait return 0[%m]\n"); */continue; }
        if (event_count < 0) {
            if (errno == EINTR) continue;
            LOGDIE("epoll_wait error[%m]\n");
        }
        struct list_head epoll_out_list = LIST_HEAD_INIT(epoll_out_list);
        for (event_index = 0; event_index < event_count; event_index++) {
            handle = (uv_handle_t *)events[event_index].data.ptr;
            handle->events = events[event_index].events;
            if (handle->is_in_epoll_out_list == 0) { list_add_tail(&handle->node_for_epoll_out, &epoll_out_list); handle->is_in_epoll_out_list = 1; }
        }
        while ((handle = list_first_entry_or_null(&epoll_out_list, uv_handle_t, node_for_epoll_out))) {
            list_del(&handle->node_for_epoll_out); handle->is_in_epoll_out_list = 0;
            if (handle->is_close_called) continue;
            int getsockopt_done = 0;
            if (handle->events & EPOLLIN) {
                if (handle == (uv_handle_t *)&uv_loop->uv_timeout) {
                    char buf[1000]; while (read(uv_loop->uv_timeout.pipes[0], buf, sizeof(buf)) > 0);
                } else if (handle == (uv_handle_t *)&uv_loop->uv_getaddrinfo_result) {
                    char buf[1000]; while (read(uv_loop->uv_getaddrinfo_result.pipes[0], buf, sizeof(buf)) > 0);
                    pthread_mutex_lock(&uv_loop->getaddrinfo_resultlist_lock);
                    uv_getaddrinfo_t *req, *n;
                    list_for_each_entry_safe(req, n, &uv_loop->getaddrinfo_resultlist, node) {
                        list_del(&req->node);
                        if (req->service) { free(req->service); req->service = NULL; }
                        if (req->hostname) { free(req->hostname); req->hostname = NULL; }
                        //if (status == UV_ECANCELED) {
                        //    assert(req->retcode == 0);
                        //    req->retcode = UV_EAI_CANCELED;
                        //}
                        if (req->cb == NULL) LOGDIE("ddddddddddddddddd\n");
                        if (req->cb) req->cb(req, req->retcode, req->addrinfo);
                    }
                    pthread_mutex_unlock(&uv_loop->getaddrinfo_resultlist_lock);
                } else {
                    switch(handle->type) {
                        case UV_TYPE_ASYNC:
                            uv_async = (uv_async_t *)handle;
                            char buf[1000]; while (read(uv_async->pipe_fd[0], buf, sizeof(buf)) > 0) { }
                            uv_async->cb(uv_async);
                            break;
                        case UV_TYPE_UDP:
                            uv_udp = (uv_udp_t *) handle;
                            ADD_UV_UDP_TO_READ_UV_UDP_TASKLIST(uv_udp);
                            break;
                        case UV_TYPE_TCP:
                            uv_tcp = (uv_tcp_t *)handle;
                            if (uv_tcp->is_connecting) {
                                getsockopt_done = 1;
                                int getsockopt_option_value; socklen_t getsockopt_option_len = sizeof(int);
                                if (getsockopt(uv_tcp->fd, SOL_SOCKET, SO_ERROR, &getsockopt_option_value, &getsockopt_option_len) || getsockopt_option_value) {
                                    if (0) {
                                    } else if (getsockopt_option_value == EINPROGRESS) {
                                    } else if (getsockopt_option_value == ECONNREFUSED) { uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, UV_ECONNREFUSED);
                                    } else if (getsockopt_option_value == ECONNRESET  ) { uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, UV_ECONNRESET  );
                                    } else if (getsockopt_option_value == ETIMEDOUT   ) { uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, UV_ETIMEDOUT   );
                                    } else { LOGFEW("bug, fix me[getsockopt_option_value %d errno %d]\n", getsockopt_option_value, errno); uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, UV_UNKNOWN);
                                    }
                                } else {
                                    uv_tcp->is_connecting = 0;
                                    uv_tcp->is_finish_handshake = 1;
                                    uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, 0);
                                    ADD_UV_TCP_TO_WRITE_UV_TCP_TASKLIST(uv_tcp);
                                    ADD_UV_TCP_TO_READ_UV_TCP_TASKLIST(uv_tcp, 1);
                                }
                                continue; //must continue, because cb may destory uv_tcp
                            }
                            ADD_UV_TCP_TO_READ_UV_TCP_TASKLIST(uv_tcp, 0);
                            break;
                        default:
                            LOGDIE("unknown type %u dddddd\n", handle->type);
                            break;
                    }
                }
            }
            if (handle->events & EPOLLOUT) {
                switch(handle->type) {
                    case UV_TYPE_TCP:
                        uv_tcp = (uv_tcp_t *)handle;
                        uv_tcp->epoll_say_readable = 1;
                        if (getsockopt_done == 0 && uv_tcp->is_connecting) {
                            int getsockopt_option_value; socklen_t getsockopt_option_len = sizeof(int);
                            if (getsockopt(uv_tcp->fd, SOL_SOCKET, SO_ERROR, &getsockopt_option_value, &getsockopt_option_len) || getsockopt_option_value) {
                                if (0) {
                                } else if (getsockopt_option_value == EINPROGRESS) {
                                } else if (getsockopt_option_value == ECONNREFUSED) { uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, UV_ECONNREFUSED);
                                } else if (getsockopt_option_value == ECONNRESET  ) { uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, UV_ECONNRESET  );
                                } else { LOGFEW("bug, fix me[getsockopt_option_value %d errno %d]\n", getsockopt_option_value, errno); uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, UV_UNKNOWN);
                                }
                            } else {
                                uv_tcp->is_connecting = 0;
                                uv_tcp->is_finish_handshake = 1;
                                ADD_UV_TCP_TO_WRITE_UV_TCP_TASKLIST(uv_tcp);
                                uv_tcp->uv_connect->uv_connect_cb(uv_tcp->uv_connect, 0);
                            }
                            continue; //must continue, because cb may destory uv_tcp
                        }
                        if (uv_tcp->is_finish_handshake) {
                            ADD_UV_TCP_TO_WRITE_UV_TCP_TASKLIST(uv_tcp);
                        }
                        break;
                   default:
                        LOGDIE("dddddd\n");
                        break;
                }
            }
        }
    }
    return 0;
}

void *child_uv_loop_thread_func(void *arg)
{
    LOGINF("UV: pthread %lu created\n", pthread_self());
    pthread_detach(pthread_self());
    uv_loop_t *uv_loop = arg;
    uv_run(uv_loop, UV_RUN_ONCE);
    uv_loop_close(uv_loop);
    LOGINF("UV: pthread %lu destoryed\n", pthread_self());
    return NULL;
}

#endif
